{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "source": [
        "# **Web Page RAG**\n",
        "\n",
        "Authored by [Kalyan KS](https://www.linkedin.com/in/kalyanksnlp/). To stay updated with LLM, RAG and Agent updates, you can follow me on [Twitter](https://x.com/kalyan_kpl).\n",
        "\n",
        "- Step-1 : Extract the web page text\n",
        "- Step-2 : Chunk the extracted web page text\n",
        "- Step-3 : Create a vector store with the extracted web page text chunks\n",
        "- Step-4 : Create a retriever which will return the relevant chunks\n",
        "- Step-5 : Build context from the relevant chunk texts\n",
        "- Step-6 : Build the RAG chain using rag prompt, LLM and string output parser.\n",
        "- Step-7 : Run the RAG chain to get the answer."
      ],
      "metadata": {
        "id": "bkvZp-8oJxfb"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## **Install and import libraries**\n"
      ],
      "metadata": {
        "id": "WX1Zty3aK8dF"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "!pip install -qU langchain langchain-community langchain-text-splitters\n",
        "!pip install -qU langchain-openai langchain-chroma"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ieCqdSLiK-3V",
        "outputId": "86a3df99-f99e-4289-ee2e-8b74dc6199a7"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.5/2.5 MB\u001b[0m \u001b[31m29.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m50.9/50.9 kB\u001b[0m \u001b[31m3.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m67.3/67.3 kB\u001b[0m \u001b[31m3.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Installing build dependencies ... \u001b[?25l\u001b[?25hdone\n",
            "  Getting requirements to build wheel ... \u001b[?25l\u001b[?25hdone\n",
            "  Preparing metadata (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m54.9/54.9 kB\u001b[0m \u001b[31m3.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m611.1/611.1 kB\u001b[0m \u001b[31m13.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.4/2.4 MB\u001b[0m \u001b[31m49.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.2/1.2 MB\u001b[0m \u001b[31m51.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m278.6/278.6 kB\u001b[0m \u001b[31m17.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m94.8/94.8 kB\u001b[0m \u001b[31m6.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m65.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m101.6/101.6 kB\u001b[0m \u001b[31m6.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m13.3/13.3 MB\u001b[0m \u001b[31m83.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m55.9/55.9 kB\u001b[0m \u001b[31m3.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m177.4/177.4 kB\u001b[0m \u001b[31m12.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m65.0/65.0 kB\u001b[0m \u001b[31m4.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m118.7/118.7 kB\u001b[0m \u001b[31m8.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m73.0/73.0 kB\u001b[0m \u001b[31m5.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m62.3/62.3 kB\u001b[0m \u001b[31m4.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m459.8/459.8 kB\u001b[0m \u001b[31m19.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m319.7/319.7 kB\u001b[0m \u001b[31m19.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m71.5/71.5 kB\u001b[0m \u001b[31m4.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m4.0/4.0 MB\u001b[0m \u001b[31m57.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m452.6/452.6 kB\u001b[0m \u001b[31m24.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m46.0/46.0 kB\u001b[0m \u001b[31m3.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m86.8/86.8 kB\u001b[0m \u001b[31m5.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Building wheel for pypika (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain_community.document_loaders import WebBaseLoader\n",
        "from langchain_text_splitters  import RecursiveCharacterTextSplitter\n",
        "from langchain_chroma import Chroma\n",
        "from langchain_openai import OpenAIEmbeddings, ChatOpenAI\n",
        "from langchain_core.prompts import ChatPromptTemplate\n",
        "from langchain_core.output_parsers import StrOutputParser\n",
        "from langchain_core.runnables import RunnableLambda"
      ],
      "metadata": {
        "id": "TXetwTFYLA8X",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "56debe2e-5618-422a-f499-05876b7aee0f"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "WARNING:langchain_community.utils.user_agent:USER_AGENT environment variable not set, consider setting it to identify your requests.\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## **Set up LLM API Key**\n",
        "\n",
        "- Save the `OPENAI_API_KEY` in Google Colab Secrets"
      ],
      "metadata": {
        "id": "bg-Xr6WgLBVj"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "from google.colab import userdata\n",
        "import os\n",
        "os.environ[\"OPENAI_API_KEY\"] = userdata.get('OPENAI_API_KEY')"
      ],
      "metadata": {
        "id": "pnsVEcU1LFwZ"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## **Extract YouTube video transcript**"
      ],
      "metadata": {
        "id": "0MwnhbIrLIHf"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "from typing import List\n",
        "from langchain.schema import Document\n",
        "\n",
        "def wp_text(page_url: str) -> List[Document]:\n",
        "    \"\"\"\n",
        "    Extracts text from the web page using WebBaseLoader.\n",
        "\n",
        "    Parameters:\n",
        "    page_url (str): The URL of the web page.\n",
        "\n",
        "    Returns:\n",
        "    List[Document]: A list of Document objects containing the text.\n",
        "    \"\"\"\n",
        "\n",
        "    print(\"Web page text is extracted...\")\n",
        "\n",
        "    loader = WebBaseLoader(page_url)\n",
        "    webpage_text = loader.load()\n",
        "\n",
        "    return webpage_text"
      ],
      "metadata": {
        "id": "HBpkh5fALREj"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "page_url = \"https://x.ai/blog/grok-2\"\n",
        "webpage_text = wp_text(page_url)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "vnHyVr2HQeJa",
        "outputId": "44c4c7c6-b172-4366-8299-7067a811b88a"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Web page text is extracted...\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "print(webpage_text)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Y_fb-lCUap4X",
        "outputId": "b4671621-47bd-4258-8a51-8de67e1c7462"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "[Document(metadata={'source': 'https://x.ai/blog/grok-2', 'title': 'Grok-2 Beta Release', 'description': 'We announce our new Grok-2 and Grok-2 mini models.', 'language': 'en'}, page_content='Grok-2 Beta ReleaseGrokAPIBlogAboutCareersMenuAugust 13, 2024Grok-2 Beta ReleaseGrok-2 is our frontier language model with state-of-the-art reasoning capabilities. This release includes two members of the Grok family: Grok-2 and Grok-2 mini. Both models are now being released to Grok users on the \\uf8ffùïè platform.We are excited to release an early preview of Grok-2, a significant step forward from our previous model Grok-1.5, featuring frontier capabilities in chat, coding, and reasoning. At the same time, we are introducing Grok-2 mini, a small but capable sibling of Grok-2. An early version of Grok-2 has been tested on the LMSYS leaderboard under the name \"sus-column-r.\" At the time of this blog post, it is outperforming both Claude 3.5 Sonnet and GPT-4-Turbo.Grok-2 and Grok-2 mini are currently in beta on \\uf8ffùïè, and we are also making both models available through our enterprise API later this month.Grok-2 language model and chat capabilitiesWe introduced an early version of Grok-2 under the name \"sus-column-r\" into the LMSYS chatbot arena, a popular competitive language model benchmark. It outperforms both Claude and GPT-4 on the LMSYS leaderboard in terms of its overall Elo score.\\n\\nInternally, we employ a comparable process to evaluate our models. Our AI Tutors engage with our models across a variety of tasks that reflect real-world interactions with Grok. During each interaction, the AI Tutors are presented with two responses generated by Grok. They select the superior response based on specific criteria outlined in our guidelines. We focused on evaluating model capabilities in two key areas: following instructions and providing accurate, factual information. Grok-2 has shown significant improvements in reasoning with retrieved content and in its tool use capabilities, such as correctly identifying missing information, reasoning through sequences of events, and discarding irrelevant posts.BenchmarksWe evaluated the Grok-2 models across a series of academic benchmarks that included reasoning, reading comprehension, math, science, and coding. Both Grok-2 and Grok-2 mini demonstrate significant improvements over our previous Grok-1.5 model. They achieve performance levels competitive to other frontier models in areas such as graduate-level science knowledge (GPQA), general knowledge (MMLU, MMLU-Pro), and math competition problems (MATH). Additionally, Grok-2 excels in vision-based tasks, delivering state-of-the-art performance in visual math reasoning (MathVista) and in document-based question answering (DocVQA).\\nBenchmarkGrok-1.5Grok-2 mini‚Ä°Grok-2‚Ä°GPT-4 Turbo*Claude 3 Opus‚Ä†Gemini Pro 1.5Llama 3 405BGPT-4o*Claude 3.5 Sonnet‚Ä†GPQA35.9%51.0%56.0%48.0%50.4%46.2%51.1%53.6%59.6%MMLU81.3%86.2%87.5%86.5%85.7%85.9%88.6%88.7%88.3%MMLU-Pro51.0%72.0%75.5%63.7%68.5%69.0%73.3%72.6%76.1%MATH¬ß50.6%73.0%76.1%72.6%60.1%67.7%73.8%76.6%71.1%HumanEval¬∂74.1%85.7%88.4%87.1%84.9%71.9%89.0%90.2%92.0%MMMU53.6%63.2%66.1%63.1%59.4%62.2%64.5%69.1%68.3%MathVista52.8%68.1%69.0%58.1%50.5%63.9%‚Äî63.8%67.7%DocVQA85.6%93.2%93.6%87.2%89.3%93.1%92.2%92.8%95.2%\\n* GPT-4-Turbo and GPT-4o scores are from the May 2024 release.\\n‚Ä† Claude 3 Opus and Claude 3.5 Sonnet scores are from the June 2024 release.\\n‚Ä° Grok-2 MMLU, MMLU-Pro, MMMU and MathVista were evaluated using 0-shot CoT.\\n¬ß For MATH, we present maj@1 results.\\n¬∂ For HumanEval, we report pass@1 benchmark scores.Experience Grok with real-time information on \\uf8ffùïèOver the past few months, we\\'ve been continuously improving Grok on the \\uf8ffùïè platform. Today, we\\'re introducing the next evolution of the Grok experience, featuring a redesigned interface and new features.\\n\\n\\uf8ffùïè Premium and Premium+ users will have access to two new models: Grok-2 and Grok-2 mini. Grok-2 is our state-of-the-art AI assistant with advanced capabilities in both text and vision understanding, integrating real-time information from the \\uf8ffùïè platform, accessible through the Grok tab in the \\uf8ffùïè app. Grok-2 mini is our small but capable model that offers a balance between speed and answer quality. Compared to its predecessor, Grok-2 is more intuitive, steerable, and versatile across a wide range of tasks, whether you\\'re seeking answers, collaborating on writing, or solving coding tasks. In collaboration with Black Forest Labs, we are experimenting with their FLUX.1 model to expand Grok‚Äôs capabilities on \\uf8ffùïè. If you are a Premium or Premium+ subscriber, make sure to update to the latest version of the \\uf8ffùïè app in order to beta test Grok-2.Build with Grok using the Enterprise APIWe are also releasing Grok-2 and Grok-2 mini to developers through our new enterprise API platform later this month. Our upcoming API is built on a new bespoke tech stack that allows multi-region inference deployments for low-latency access across the world. We offer enhanced security features such as mandatory multi-factor authentication (e.g. using a Yubikey, Apple TouchID, or TOTP), rich traffic statistics, and advanced billing analytics (incl. detailed data exports). We further offer a management API that allows you to integrate team, user, and billing management into your existing in-house tools and services. Join our newsletter to get notified when we launch later this month.What is next?Grok-2 and Grok-2 mini are being rolled out on \\uf8ffùïè. We are very excited about their applications to a range of AI-driven features, such as enhanced search capabilities, gaining deeper insights on \\uf8ffùïè posts, and improved reply functions, all powered by Grok. Soon, we will release a preview of multimodal understanding as a core part of the Grok experience on \\uf8ffùïè and API.Since announcing Grok-1 in November 2023, xAI has been moving at an extraordinary pace, driven by a small team with the highest talent density. We have introduced Grok-2, positioning us at the forefront of AI development. Our focus is on advancing core reasoning capabilities with our new compute cluster. We will have many more developments to share in the coming months. We are looking for individuals to join our small, focused team dedicated to building the most impactful innovations for the future of humanity. Apply to our positions here.GrokAPILegalPrivacy Policy\\n')]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "print(f\"Number of documents = {len(webpage_text)}\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "BH6IAjYyWdpG",
        "outputId": "c9f5c942-2a28-49be-96cf-25b89a0c9427"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Number of documents = 1\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## **Chunk Transcript text**"
      ],
      "metadata": {
        "id": "jLqBvd_JLTb-"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "def wp_chunk(webpage_text: List[Document]) -> List[Document]:\n",
        "    \"\"\"\n",
        "    Splits extracted web page text into smaller chunks using RecursiveCharacterTextSplitter.\n",
        "\n",
        "    Parameters:\n",
        "    webpage_text (List[Document]): A list of Document objects containing extracted web page text.\n",
        "\n",
        "    Returns:\n",
        "    List[Document]: A list of chunked Document objects.\n",
        "    \"\"\"\n",
        "\n",
        "    print(\"Web page text is chunked....\")\n",
        "\n",
        "    text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)\n",
        "    chunks = text_splitter.split_documents(webpage_text)\n",
        "\n",
        "    return chunks"
      ],
      "metadata": {
        "id": "uK1aFrhvLWbp"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "chunks = wp_chunk(webpage_text)"
      ],
      "metadata": {
        "id": "TdDmlfxkROZ_",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "40bc29d4-e2df-4037-a0c2-6808bb3f66de"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Web page text is chunked....\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "print(f\"Number of chunks = {len(chunks)}\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "3VzMTYugRRCW",
        "outputId": "f5d7d94b-13b2-4aca-c9ac-a41d427784c8"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Number of chunks = 9\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "print(chunks[0])"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "B2wW4EJXXEo6",
        "outputId": "ee549176-643c-4c6e-b902-2928659cc84b"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "page_content='Grok-2 Beta ReleaseGrokAPIBlogAboutCareersMenuAugust 13, 2024Grok-2 Beta ReleaseGrok-2 is our frontier language model with state-of-the-art reasoning capabilities. This release includes two members of the Grok family: Grok-2 and Grok-2 mini. Both models are now being released to Grok users on the ùïè platform.We are excited to release an early preview of Grok-2, a significant step forward from our previous model Grok-1.5, featuring frontier capabilities in chat, coding, and reasoning. At the same time, we are introducing Grok-2 mini, a small but capable sibling of Grok-2. An early version of Grok-2 has been tested on the LMSYS leaderboard under the name \"sus-column-r.\" At the time of this blog post, it is outperforming both Claude 3.5 Sonnet and GPT-4-Turbo.Grok-2 and Grok-2 mini are currently in beta on ùïè, and we are also making both models available through our enterprise API later this month.Grok-2 language model and chat capabilitiesWe introduced an early version of Grok-2' metadata={'source': 'https://x.ai/blog/grok-2', 'title': 'Grok-2 Beta Release', 'description': 'We announce our new Grok-2 and Grok-2 mini models.', 'language': 'en'}\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## **Create Vector Store**"
      ],
      "metadata": {
        "id": "FqAC3V1WLdtW"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Set the chroma DB path\n",
        "current_dir = \"/content/rag\"\n",
        "persistent_directory = os.path.join(current_dir, \"db\", \"chroma_db_wp\")"
      ],
      "metadata": {
        "id": "qZ5ls-3uLh8s"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "def create_vector_store(chunks: List[Document], db_path: str) -> Chroma:\n",
        "    \"\"\"\n",
        "    Creates a Chroma vector store from chunked documents.\n",
        "\n",
        "    Parameters:\n",
        "    chunks (List[Document]): A list of chunked Document objects.\n",
        "    db_path (str): The directory path to persist the vector store.\n",
        "\n",
        "    Returns:\n",
        "    Chroma: A Chroma vector store containing the embedded documents.\n",
        "    \"\"\"\n",
        "\n",
        "    print(\"Chrome vector store is created...\\n\")\n",
        "\n",
        "    embedding_model = OpenAIEmbeddings(model=\"text-embedding-3-small\")\n",
        "    db = Chroma.from_documents(documents=chunks, embedding=embedding_model, persist_directory=db_path)\n",
        "\n",
        "    return db"
      ],
      "metadata": {
        "id": "_30SvTV7Lg1K"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "db = create_vector_store(chunks, persistent_directory)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "XS8knuW4RiQ8",
        "outputId": "0a79028e-311a-4969-8e92-115f255ef062"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Chrome vector store is created...\n",
            "\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## **Retrieve relevant chunks**"
      ],
      "metadata": {
        "id": "fV2W-AlfLwFX"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "def retrieve_context(db: Chroma, query: str) -> List[Document]:\n",
        "    \"\"\"\n",
        "    Retrieves relevant document chunks from the Chroma vector store based on a query.\n",
        "\n",
        "    Parameters:\n",
        "    db (Chroma): The Chroma vector store containing embedded documents.\n",
        "    query (str): The query string to search for relevant document chunks.\n",
        "\n",
        "    Returns:\n",
        "    List[Document]: A list of retrieved relevant document chunks.\n",
        "    \"\"\"\n",
        "\n",
        "    retriever = db.as_retriever(search_type=\"similarity\", search_kwargs={\"k\": 2})\n",
        "    print(\"Relevant chunks are retrieved...\\n\")\n",
        "    relevant_chunks = retriever.invoke(query)\n",
        "\n",
        "    return relevant_chunks"
      ],
      "metadata": {
        "id": "7GPAc2iGL3bK"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "query = 'What is Grok 2?'\n",
        "\n",
        "relevant_chunks = retrieve_context(db, query)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "UO-clF3KRrZj",
        "outputId": "327bf023-5d63-4ab2-d5c2-5a526bd69a9f"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Relevant chunks are retrieved...\n",
            "\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "print(f\"Number of relevant chunks = {len(relevant_chunks)}\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ytjpbOpaRzxI",
        "outputId": "2c5adbfd-6dae-4dec-af1a-aa0e2f44021b"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Number of relevant chunks = 2\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "for i, chunk in enumerate(relevant_chunks):\n",
        "  print(f\"Chunk-{i}\")\n",
        "  print(chunk)\n",
        "  print(\"\\n\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "rk8DZzajR2Ya",
        "outputId": "5e5c61e5-75ea-4ae0-f86f-0188fa27e45f"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Chunk-0\n",
            "page_content='Grok-2 Beta ReleaseGrokAPIBlogAboutCareersMenuAugust 13, 2024Grok-2 Beta ReleaseGrok-2 is our frontier language model with state-of-the-art reasoning capabilities. This release includes two members of the Grok family: Grok-2 and Grok-2 mini. Both models are now being released to Grok users on the ùïè platform.We are excited to release an early preview of Grok-2, a significant step forward from our previous model Grok-1.5, featuring frontier capabilities in chat, coding, and reasoning. At the same time, we are introducing Grok-2 mini, a small but capable sibling of Grok-2. An early version of Grok-2 has been tested on the LMSYS leaderboard under the name \"sus-column-r.\" At the time of this blog post, it is outperforming both Claude 3.5 Sonnet and GPT-4-Turbo.Grok-2 and Grok-2 mini are currently in beta on ùïè, and we are also making both models available through our enterprise API later this month.Grok-2 language model and chat capabilitiesWe introduced an early version of Grok-2' metadata={'description': 'We announce our new Grok-2 and Grok-2 mini models.', 'language': 'en', 'source': 'https://x.ai/blog/grok-2', 'title': 'Grok-2 Beta Release'}\n",
            "\n",
            "\n",
            "Chunk-1\n",
            "page_content='and Grok-2 mini demonstrate significant improvements over our previous Grok-1.5 model. They achieve performance levels competitive to other frontier models in areas such as graduate-level science knowledge (GPQA), general knowledge (MMLU, MMLU-Pro), and math competition problems (MATH). Additionally, Grok-2 excels in vision-based tasks, delivering state-of-the-art performance in visual math reasoning (MathVista) and in document-based question answering (DocVQA).' metadata={'description': 'We announce our new Grok-2 and Grok-2 mini models.', 'language': 'en', 'source': 'https://x.ai/blog/grok-2', 'title': 'Grok-2 Beta Release'}\n",
            "\n",
            "\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## **Build context**"
      ],
      "metadata": {
        "id": "BcJbxTaqL7QE"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "def build_context(relevant_chunks: List[Document]) -> str:\n",
        "    \"\"\"\n",
        "    Builds a context string from retrieved relevant document chunks.\n",
        "\n",
        "    Parameters:\n",
        "    relevant_chunks (List[Document]): A list of retrieved relevant document chunks.\n",
        "\n",
        "    Returns:\n",
        "    str: A concatenated string containing the content of the relevant chunks.\n",
        "    \"\"\"\n",
        "\n",
        "    print(\"Context is built from relevant chunks\")\n",
        "    context = \"\\n\\n\".join([chunk.page_content for chunk in relevant_chunks])\n",
        "\n",
        "    return context"
      ],
      "metadata": {
        "id": "xRZ2HLDxMAcP"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "context = build_context(relevant_chunks)"
      ],
      "metadata": {
        "id": "Enka2YvTSULr",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "f4d90b6c-3855-44fd-f7ef-eb795352e79e"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Context is built from relevant chunks\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "print(context)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "S3Ndsd-4SWg1",
        "outputId": "45a08a13-996f-48de-8016-ba81affaa7f8"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Grok-2 Beta ReleaseGrokAPIBlogAboutCareersMenuAugust 13, 2024Grok-2 Beta ReleaseGrok-2 is our frontier language model with state-of-the-art reasoning capabilities. This release includes two members of the Grok family: Grok-2 and Grok-2 mini. Both models are now being released to Grok users on the ùïè platform.We are excited to release an early preview of Grok-2, a significant step forward from our previous model Grok-1.5, featuring frontier capabilities in chat, coding, and reasoning. At the same time, we are introducing Grok-2 mini, a small but capable sibling of Grok-2. An early version of Grok-2 has been tested on the LMSYS leaderboard under the name \"sus-column-r.\" At the time of this blog post, it is outperforming both Claude 3.5 Sonnet and GPT-4-Turbo.Grok-2 and Grok-2 mini are currently in beta on ùïè, and we are also making both models available through our enterprise API later this month.Grok-2 language model and chat capabilitiesWe introduced an early version of Grok-2\n",
            "\n",
            "and Grok-2 mini demonstrate significant improvements over our previous Grok-1.5 model. They achieve performance levels competitive to other frontier models in areas such as graduate-level science knowledge (GPQA), general knowledge (MMLU, MMLU-Pro), and math competition problems (MATH). Additionally, Grok-2 excels in vision-based tasks, delivering state-of-the-art performance in visual math reasoning (MathVista) and in document-based question answering (DocVQA).\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## **Combine all the steps into one function**"
      ],
      "metadata": {
        "id": "XDlTllCSMOSE"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "import os\n",
        "from typing import Dict\n",
        "from langchain_openai import OpenAIEmbeddings\n",
        "from langchain_chroma import Chroma\n",
        "\n",
        "def get_context(inputs: Dict[str, str]) -> Dict[str, str]:\n",
        "    \"\"\"\n",
        "    Creates or loads a vector store for the video transcript and retrieves relevant chunks based on a query.\n",
        "\n",
        "    Args:\n",
        "        inputs (Dict[str, str]): A dictionary containing the following keys:\n",
        "            - 'page_url' (str): Web page URL\n",
        "            - 'query' (str): The user query.\n",
        "            - 'db_path' (str): Path to the vector database.\n",
        "\n",
        "    Returns:\n",
        "        Dict[str, str]: A dictionary containing:\n",
        "            - 'context' (str): Extracted relevant context.\n",
        "            - 'query' (str): The user query.\n",
        "    \"\"\"\n",
        "    page_url, query, db_path  = inputs['page_url'], inputs['query'], inputs['db_path']\n",
        "\n",
        "    # Create new vector store if it does not exist\n",
        "    if not os.path.exists(db_path):\n",
        "        print(\"Creating a new vector store...\\n\")\n",
        "        webpage_text = wp_text(page_url)\n",
        "        chunks = wp_chunk(webpage_text)\n",
        "        db = create_vector_store(chunks, db_path)\n",
        "\n",
        "    # Load the existing vector store\n",
        "    else:\n",
        "        print(\"Loading the existing vector store\\n\")\n",
        "        embedding_model = OpenAIEmbeddings(model=\"text-embedding-3-small\")\n",
        "        db = Chroma(persist_directory=db_path, embedding_function=embedding_model)\n",
        "\n",
        "    relevant_chunks = retrieve_context(db, query)\n",
        "    context = build_context(relevant_chunks)\n",
        "\n",
        "    return {'context': context, 'query': query}"
      ],
      "metadata": {
        "id": "cPKy-j4BMgHo"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## **Build RAG chain**"
      ],
      "metadata": {
        "id": "O2MVf4vxM4sv"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "template = \"\"\" You are an AI model trained for question answering. You should answer the\n",
        "  given question based on the given context only.\n",
        "  Question : {query}\n",
        "  \\n\n",
        "  Context : {context}\n",
        "  \\n\n",
        "  If the answer is not present in the given context, respond as: The answer to this question is not available\n",
        "  in the provided content.\n",
        "  \"\"\"\n",
        "\n",
        "rag_prompt = ChatPromptTemplate.from_template(template)\n",
        "\n",
        "llm = ChatOpenAI(model='gpt-4o-mini')\n",
        "\n",
        "str_parser = StrOutputParser()\n",
        "\n",
        "rag_chain = (\n",
        "    RunnableLambda(get_context)\n",
        "    | rag_prompt\n",
        "    | llm\n",
        "    | str_parser\n",
        ")"
      ],
      "metadata": {
        "id": "x9KX2O3OM8Yu"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## **Run RAG chain**"
      ],
      "metadata": {
        "id": "z-I63SUYNLT5"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Set the chroma DB path\n",
        "current_dir = \"/content/rag\"\n",
        "persistent_directory = os.path.join(current_dir, \"db\", \"chroma_db_wp\")"
      ],
      "metadata": {
        "id": "ZiqL9tnZNQ1v"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Web page URL\n",
        "page_url = \"https://x.ai/blog/grok-2\""
      ],
      "metadata": {
        "id": "MWOhvXCJMNsK"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Write the query\n",
        "query = 'What is Grok 2?'"
      ],
      "metadata": {
        "id": "0WIwZN65NJLW"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "answer = rag_chain.invoke({'page_url':page_url, 'query':query, 'db_path':persistent_directory})"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "FkmSBhOJNKeC",
        "outputId": "36f5c3c4-bb2b-4ff2-8dfd-067eb408cb20"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Loading the existing vector store\n",
            "\n",
            "Relevant chunks are retrieved...\n",
            "\n",
            "Context is built from relevant chunks\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "print(f\"Query:{query}\\n\")\n",
        "print(f\"Generated answer:{answer}\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "gyPrNA7iNSiR",
        "outputId": "54d3ab37-a3ae-4e31-cd14-efd6882bae08"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Query:What is Grok 2?\n",
            "\n",
            "Generated answer:Grok-2 is a frontier language model that features state-of-the-art reasoning capabilities, representing a significant advancement over its predecessor, Grok-1.5. It is designed for chat, coding, and reasoning tasks, and it is currently available in beta on the ùïè platform. Alongside Grok-2, a smaller version named Grok-2 mini is also released. Grok-2 has been tested and shown to outperform other models like Claude 3.5 Sonnet and GPT-4-Turbo in various performance metrics, including graduate-level science knowledge, general knowledge, and math problems, as well as excelling in vision-based tasks.\n"
          ]
        }
      ]
    }
  ]
}